package cn.xianshu.elasticsearch;

import org.elasticsearch.action.delete.DeleteRequestBuilder;
import org.elasticsearch.action.delete.DeleteResponse;
import org.elasticsearch.action.get.GetRequestBuilder;
import org.elasticsearch.action.get.GetResponse;
import org.elasticsearch.action.index.IndexRequestBuilder;
import org.elasticsearch.action.index.IndexResponse;
import org.elasticsearch.action.search.SearchRequestBuilder;
import org.elasticsearch.action.search.SearchResponse;
import org.elasticsearch.action.update.UpdateRequestBuilder;
import org.elasticsearch.action.update.UpdateResponse;
import org.elasticsearch.client.transport.TransportClient;
import org.elasticsearch.common.settings.Settings;
import org.elasticsearch.common.transport.InetSocketTransportAddress;
import org.elasticsearch.index.query.BoolQueryBuilder;
import org.elasticsearch.index.query.QueryBuilders;
import org.elasticsearch.search.SearchHit;
import org.elasticsearch.search.SearchHits;
import org.elasticsearch.search.sort.SortOrder;
import org.elasticsearch.transport.client.PreBuiltTransportClient;
import org.junit.Test;
import java.net.InetAddress;
import java.net.UnknownHostException;
import java.util.HashMap;
import java.util.Map;

/**
 * ES的 CRUD
 */
public class Test_ES {
    /**
     * 连接ES获取Client对象
     * @throws UnknownHostException
     */
    private TransportClient getClient() {
        Settings settings = Settings.builder()
                .put("client.transport.sniff", true).build();
        TransportClient client = null;
        try {
            client = new PreBuiltTransportClient(settings)
                    .addTransportAddress(new InetSocketTransportAddress(InetAddress.getByName("127.0.0.1"), 9300));
        } catch (UnknownHostException e) {
            e.printStackTrace();
        }
        return client;
    }


    /**
     * 添加
     */
    @Test
    public void add(){
        // 建立连接
        TransportClient client = getClient();
        // 创建索引
        IndexRequestBuilder indexRequestBuilder = client.prepareIndex("pethome", "user", "1");
        // 添加文档
        Map<String, Object> data = new HashMap<>();
        data.put("id", 1L);
        data.put("username", "圆圆");
        data.put("realname", "贤贤");
        data.put("age", 21);
        data.put("sex", 1);
        IndexResponse indexResponse = indexRequestBuilder.setSource(data).get();
        System.out.println(indexResponse);
    }

    /**
     * 修改
     */
    @Test
    public void update(){
        // 获取链接
        TransportClient client = getClient();
        // 修改
        UpdateRequestBuilder updateRequestBuilder = client.prepareUpdate("pethome", "user", "1");
        // 修改内容
        Map<String, Object> data = new HashMap<>();
        data.put("id", 1L);
        data.put("username", "花花");
        data.put("realname", "贤贤");
        data.put("age", 21);

        // 结果
        UpdateResponse updateResponse = updateRequestBuilder.setDoc(data).get();
        System.out.println(updateResponse);
    }


    /**
     * 删除
     */
    @Test
    public void delete(){
        // 获取连接
        TransportClient client = getClient();
        // 删除
        DeleteRequestBuilder deleteRequestBuilder = client.prepareDelete("pethome", "user", "1");
        // 结果
        DeleteResponse deleteResponse = deleteRequestBuilder.get();
        System.out.println(deleteResponse);
    }


    /**
     * 获取
     */
    @Test
    public void get(){
        // 获取链接
        TransportClient client = getClient();
        // 索引
        GetRequestBuilder getRequestBuilder = client.prepareGet("pethome", "user", "1");

        GetResponse getFields = getRequestBuilder.get();
        System.out.println(getFields.getSource());
    }

    /**
     * 综合查询
     * DSL查询， 查询用户， username，为贤贤的（查询） sex为（男）， age 在10 ——30 之间的（过滤）
     * 按期age排序倒排， 查询第一页 ， 每页10条数据
     */
    @Test
    public void search(){
        // 获取链接
        TransportClient client = getClient();
        // 指定搜索的索引库
        SearchRequestBuilder pethome = client.prepareSearch("pethome");
        // 排序
        pethome.addSort("age", SortOrder.DESC); // 倒排
        // 分页
        pethome.setFrom(0);
        pethome.setSize(1); // 每页条数
        // 查询条件  采用子类接收才有其他方法
        BoolQueryBuilder boolQueryBuilder = QueryBuilders.boolQuery(); // new BoolQueryBuilder();
        // username   圆圆  或者 贤贤
        boolQueryBuilder.must(QueryBuilders.matchQuery("username", "圆圆 贤贤"));
        // sex 为男  age 为 10 ~ 30 之间
        boolQueryBuilder.filter(QueryBuilders.termQuery("sex", 1))
                        .filter(QueryBuilders.rangeQuery("age").gte("10").lte(30));
        // 结果
        SearchResponse searchResponse = pethome.setQuery(boolQueryBuilder).get();
        // 命中 查到结果
        SearchHits hits = searchResponse.getHits();
        // 获取总的命中数
        long totalHits = hits.getTotalHits();
        System.out.println("查到的总条数:" + totalHits);

        // 结果列表
        SearchHit[] list = hits.getHits();
        for (SearchHit fields : list) {
            Map<String, Object> source = fields.getSource();
            System.out.println(source);
        }
    }


    /**
     * 综合查询
     * DSL查询， 查询用户， username，为贤贤的（查询） sex为（男）， age 在10 ——30 之间的（过滤）
     * 按期age排序倒排， 查询第一页 ， 每页10条数据
     */
    @Test
    public void searchs(){
        // 建立连接
        TransportClient client = getClient();
        // 指定搜索引擎的索引库
        SearchRequestBuilder pethome = client.prepareSearch("pethome");
        // 分页
        pethome.setFrom(0);
        pethome.setSize(10); // 每页条数
        // 查询条件 采用子类接收才能使用其他方法
        BoolQueryBuilder boolQueryBuilder = QueryBuilders.boolQuery();
        // username查询 圆圆  或者  贤贤
        boolQueryBuilder.must(QueryBuilders.matchQuery("username", "圆圆 贤贤"));
        // age范围查询 10 ~ 50
        boolQueryBuilder.filter(QueryBuilders.termQuery("sex", "1"))
                .filter(QueryBuilders.rangeQuery("age").gte(10).lte(50));
        // 获取结果
        SearchResponse response = pethome.setQuery(boolQueryBuilder).get();
        // 命中结果
        SearchHits hits = response.getHits();
        // 命中查询到的结果
        long totalHits = hits.getTotalHits();
        // 获取命中的总数量
        System.out.println("查到的总条数:" + totalHits);
        // 结果列表
        SearchHit[] hits1 = hits.getHits();
        // 循环查询到的所有数据
        for (SearchHit fields : hits1) {
            Map<String, Object> source = fields.getSource();
            System.out.println(source);
        }
    }
}


